import { ABaseDecision } from "GameLoop/DecisionMaking/BaseDecision";
import { FactoryTaskHelper } from "GameLoop/WorldState/EntityManager/Entitys/room/factory/FactoryTaskHelper";
import { BASE_PRODUCE, BASE_PRODUCE_COMPOSE, COMMODITY_SOLD_LIMIT } from "GameLoop/WorldState/EntityManager/Entitys/room/factory/constants";
import { T3Targets } from "utils/constants/constants";
import { BaseMinerial, UnZipMinerial, ZipMinerial, goods_sold_backlist } from "utils/constants/globalconstant";
import { CoreTaskHelper } from "utils/task/coreTaskHelper";
export interface IStrategy<T>
{
    ( resource:FactoryResourceType,roomName:string,amount:number, item:DBItem):boolean
}
/**
 * 各房间的资源平衡决策
 */
export class ResourceDispatchDecision < T extends TaskType="room"> extends ABaseDecision<T>
{
    private strategyOrder:IStrategy<T>[]=[];
    constructor(WorldGetter:WorldGetter)
    {
        super(WorldGetter)
        this.strategyOrder.push(this.TryProduce.bind(this));
        this.strategyOrder.push(this.TryTerminalSend.bind(this));
        this.strategyOrder.push(this.TryGetFromMarket.bind(this));
    }
    private processingResource( resource:FactoryResourceType,roomName:string,amount:number, item:DBItem)
    {
        // 获取资源前先判断是否有多余空间
        const room_terminal = Game.rooms[roomName].terminal;
        if(resource!= RESOURCE_ENERGY && room_terminal&&  room_terminal.store.getFreeCapacity()<30000)
        {
            Game.rooms[roomName].log("warn",`补充资源 [${resource}]数量:[${amount}] 失败 终端空间不足 30000`);
            return false;
        }
        // global.LogDebug(`补充资源 [${resource}] 房间[${roomName}] 数量:[${amount}]`);
        for(const strategy of this.strategyOrder)
        {
            if(strategy(resource,roomName,amount,item))
            {
                return true;
            }
        }
        return false;
    }

    public isExpired(event: NormalEvent, region: string): boolean 
    {
        return true
    }
    private   checkResourceStats(  room:Required<Room> )
    {
        const coreentity = room.getEntity("CoreEntity"); 
        
        {
            const res = coreentity.getSurplusResource();
            const keys = Object.keys(res) as ResourceConstant[];
            for(const e of keys)
            {
                room.registerExcessResource(e,res[e] as number);
            }            
        }

        {
            const res = coreentity.getShortageResource();
            const keys = Object.keys(res) as ResourceConstant[];
            for(const e of keys)
            {
                room.registerShortageResource(e,res[e] as number);
            }            
        }
    }
    public makeTask(event: NormalEvent, region: string): IDecisionCode<T>|false
    {
        // 每次要进行资源分发的时候。更新检测一波资源情况。其他lab factory的自行注册.
      
        const factorylevels =   new Array<string[]>(6);
        for(const name of global.resourceStats.myrooms)
        {
            if(!(Game.rooms[name].terminal?.my && Game.rooms[name].getType() ==1))
            {
                continue;
            }
            const core = Game.rooms[name].getEntity("CoreEntity");
            this.checkResourceStats(Game.rooms[name] as Required<Room>);
            const factoryLevel = core.Factory?.level;
            let idx=factoryLevel?factoryLevel:0;

            if(factorylevels[idx])
            {
                factorylevels[idx].push(core.roomName);
            }
            else
            {
                factorylevels[idx] = [core.roomName];
            }
        }
        const storeDB:Record<ResourceConstant,DBItem> = global.resourceStats.getResourceDB();
        const roomorder:string[]=[];
        for(let idx=factorylevels.length-1;idx>=0;idx--)
        {
            if(factorylevels[idx])
            {
                for(const roomName of factorylevels[idx])
                {
                    roomorder.push(roomName);
                }
            }

        }
        const resourceKeys = Object.keys(storeDB);
        // global.Log.Info(`assert1 ${JSON.stringify(resourceKeys)}`)
        for(const resource of resourceKeys)
        {
            const value = storeDB[resource as ResourceConstant];
            if(value)
            {
                //要按照房间工厂等级排序。
                for(const roomName of roomorder)
                {
                    if(value.shortage[roomName])
                    {
                        let ret = this.processingResource( resource as FactoryResourceType,roomName,value.shortage[roomName],value);
                        if(ret == false && ZipMinerial[resource as MineralConstant] )
                        {
                             // 额外处理一下原矿的问题,原矿整不到就整bar
                            const bartype = ZipMinerial[resource as MineralConstant];
                            if(storeDB[bartype])
                            {
                                ret = this.processingResource( bartype as FactoryResourceType,roomName,value.shortage[roomName]/5,storeDB[bartype]);
                            }
                        }
                        if(ret)
                        {
                            // 处理完成则删除此资源得处理
                            global.resourceStats.removeShortageResource(Game.rooms[roomName],resource as ResourceConstant);
                        }
                    }
                }

            }
        }
        // 2.多余得资源出售
        // 只卖商品和指定资源，暂时只卖5级商品
        // entity.dispatchDB.forEach((dbItem,resource)=>
        for(const resource in storeDB)
        {
            const dbItem =  storeDB[resource as ResourceConstant];
            const rooms = Object.keys(dbItem.surplus);
            for(let roomName of rooms)
            {
                // global.LogDebug(`准备出售资源[factory${COMMODITIES[resource as CommodityConstant].level}]:${roomName}_${resource}_${dbItem.surplus[roomName]}`);
                if(goods_sold_backlist.has(resource as CommodityConstant))
                {
                    // 不挣钱的原材料商品不卖
                    continue;
                }
                if(!dbItem.surplus[roomName])
                {
                    // 数量为0 不卖
                    continue;
                }
                // 3.只卖商品,还有xgh2o
                const level = COMMODITIES[resource as CommodityConstant]?.level;
                if(level  )
                {
                    // 不在限制表单里，或者是比限制的表单的数量要多
                    if(!COMMODITY_SOLD_LIMIT[level] || COMMODITY_SOLD_LIMIT[level]<dbItem.surplus[roomName])
                    {
                       
                        global.market.SellResource(roomName,resource as ResourceConstant,dbItem.surplus[roomName]);
                    }

                }
                else if  (BASE_PRODUCE[resource])
                {
                    global.market.SellResource(roomName,resource as ResourceConstant,dbItem.surplus[roomName]);
                }
                else  if(resource == RESOURCE_ENERGY)
                {
                    
                    // 卖能量的情况。爆仓了
                    const core = Game.rooms[roomName].getEntity("CoreEntity");
                    if(core.freeSpace()<60000)
                    {
                        if(core.resourceCount(RESOURCE_BATTERY)>200000)
                        {
                            // 成本价出售单
                            global.market.PostSellOrder(roomName,RESOURCE_BATTERY,50000,1);
                        }
                        else if(core.resourceCount(resource)>200000)
                        {
                            global.market.PostSellOrder(roomName,resource,50000,1);
                        }
                    }
                }else  if(UnZipMinerial[resource as CommodityConstant])
                {
                    
                    // 卖能量的情况。爆仓了
                    const core = Game.rooms[roomName].getEntity("CoreEntity");
                    if(core.freeSpace()<60000)
                    {
                        const existaamount = core.resourceCount(resource as CommodityConstant)
                        if(core.resourceCount(RESOURCE_ENERGY)>50000)
                        {
                            // 成本价出售单
                            global.market.SellResource(roomName,resource as CommodityConstant,Math.min(10000,existaamount));
                        }
                        else  
                        {
                            // 爆仓促销
                            global.market.PostSellOrder(roomName,resource as CommodityConstant,Math.min(10000,existaamount),0.9);
                        }
                    }
                }
            }
        }

        // global.resourceStats.resetCahce(); 资源分发还要靠缓存计算。不能清
        return false
    }
    /**
     * 判断是否能够通过生产获得
    */
    private TryProduce( resource:FactoryResourceType,roomName:string,amount:number, item:DBItem)
    {
        //global.LogDebug(`资源处理 ->TryProduce ${roomName} ${resource}->[${amount}]`);
        if(!COMMODITIES[resource])
        {
            return false;
        }
        if(ZipMinerial[resource as MineralConstant])
        {
            // 不通过生产Bar补充，只购买
            return false;
        }
        const core = this.entityDB.getEntity("CoreEntity",roomName);
        if(COMMODITIES[resource].level && COMMODITIES[resource].level!=core.Factory?.level)
        {
            global.Log.Info(`生产此资源的等级不够 ${resource} 工厂等级`);
            return false;
        }
        const resRecord = FactoryTaskHelper.CalAllSubResourceAmount(resource,amount);
        for(let key in resRecord)
        {

            if(core.resourceCount(key as ResourceConstant)<resRecord[key as FactoryResourceType])
            {
                // 不满足 资源不足
                return false;
            }
        }
        // 生产-的是原料
        for(let key in resRecord)
        {
            if(item.surplus[key ] )
            {
                item.surplus[key ] -=resRecord[key as FactoryResourceType];
            }
        }
        // 可以执行则添加生产任务,有可能刚压缩的又被解压了。这里要限制一下啊
        const produceTask = CoreTaskHelper.getProduce(resource as CommodityConstant,amount)
        return Game.rooms[roomName].addNewTask(produceTask)
    }
 
     /**
      * 判断是否由其他房间转移,如果是基础资源可以发送原矿或者是压缩的bar
     */
    private TryTerminalSend( resource:FactoryResourceType,roomName:string,amount:number, item:DBItem)
    {
    // global.LogDebug(`资源处理 ->TryTerminalSend ${roomName} ${resource}->[${amount}]`);

        for(const  otherroom in item.surplus)
        {
            if(item.surplus[otherroom]>=amount)
            {
                item.surplus[otherroom]-=amount;
                const othercore = this.entityDB.getEntity("CoreEntity",otherroom);
                if(othercore.Terminal && othercore.Terminal.store.getUsedCapacity(RESOURCE_ENERGY)<20000)
                {
                    continue;
                }
                global.resourceStats.subtractSurplusResource(Game.rooms[otherroom],resource, amount);
                const sendtask = CoreTaskHelper.getSend( 
                otherroom,
                roomName,
                resource,
                amount
                )
            
                //
                // global.Log.Debug(`${otherroom}_${roomName}`, `资源处理 TryTerminalSend ${otherroom}  其他房间共享获得${roomName} ${resource}->[${amount}]`);
                return Game.rooms[otherroom].addNewTask(sendtask)
                
            }
        }
        return false;
    }
 
     private TryGetFromMarket( resource:MarketResourceConstant,roomName:string,amount:number, item:DBItem)
     {
         //global.LogDebug(`资源处理 ->TryGetFromMarket ${roomName} ${resource}->[${amount}]`);
         // 查询订单.
         // global.Market.CreateOrder
         // 1.计算距离
         // 2.计算能量的开销
         // 3.计算能量的价值
         // 4.加上资源的价值就是。这笔order的价值。
         // 当CR小于一定值。不不自动购买了
         if(resource == RESOURCE_ENERGY&& Game.market.credits<10000000)
         {
             return false;
         }
         if(Game.market.credits<4000000)
         {
             return false;
         }
         // 不买商品
         if(COMMODITIES[resource as FactoryResourceType]?.level)
         {
             return false;
         }
         if(BASE_PRODUCE_COMPOSE.has(resource))
         {
             return false;
         }
         if(BASE_PRODUCE[resource])
         {
             return false;
         }
         // 不买G
         if(resource == RESOURCE_POWER)
         {
             // 暂时先屏蔽G。以后再用原材料的价格计算。G的成本价
             return false;
         }
         let energy_limit = 80000;
         if(resource == RESOURCE_OPS)
         {
             energy_limit=20000;
         }
         if(resource == RESOURCE_ENERGY)
         {
             energy_limit=20000;
         }
         const othercore = this.entityDB.getEntity("CoreEntity",roomName);
         if(othercore.Terminal && othercore.Terminal.store.getUsedCapacity(RESOURCE_ENERGY)<energy_limit)
         {
             // 能量不足就挂单买啊
             global.market.PostBuyOrder(roomName,resource,amount);
             global.Log.Warning(`${roomName}:终端能量不足 挂单购买购买资源`);
             return false;
         }
         if(T3Targets.includes(resource as MineralCompoundConstant))
         {
            // T3只买到3000
            if(othercore.resourceCount(resource as MineralCompoundConstant )>=3000)
            {
                return false;
            }
         }
         const res =  global.market.BuyResource(roomName,resource,amount);
         if(!res)
         {
             global.market.PostBuyOrder(roomName,resource,amount);
             global.Log.Warning(`${roomName}:购买资源失败 挂买单购买资源`);
         }
        // global.LogDebug(`资源处理 TryGetFromMarket 市场获得${roomName} ${resource}->[${amount}]   ${res}`);
         return res;
     }
}